#ifndef SESSION_H
#define SESSION_H

#include <QString>
#include <QStringList>
#include <QSharedPointer>
#include <string>
#include <QThread>
#include <QThreadPool>
#include <QQueue>
#include <QMutex>
#include <QWaitCondition>
#include <QTcpSocket>
#include <QSslSocket>
#include <QHostAddress>
#include <QUrl>
#include <QList>
#include <QAtomicInt>
#include <QtEndian>
#include <QTimer>
#include <QEvent>
#include <QCoreApplication>

#include <google/protobuf/message.h>

#include "concurrentqueue.h"
#include "payload.h"
#include "communicationexception.h"
#include "connectionconfig.h"
#include "noncopyable.h"
#include "wireformat.h"
#include "connection.h"
#include "qslog.h"
#include "utils.h"
#include "connection.h"
#include "connectionconfig.h"
#include "connectionerrorinfo.h"
#include "type.h"

namespace apollo
{
	namespace core
	{
		typedef PayloadPtr (*LoginInfoProvider)();

		class Session : public QThread
		{
			Q_OBJECT

		public:
			explicit Session(QSharedPointer<ConnectionConfig> config, 
				QSharedPointer<WireFormat> format = QSharedPointer<WireFormat>(new WireFormat), QObject *parent = NULL);
			~Session();
			//void start();
			MessagePtr connect(MessagePtr loginRequest);

			void close();
			void write(PayloadPtr payload);
			const SessionState & getState() const { return state;}
			void setLoginInfoProvider(LoginInfoProvider provider) {this->provider = provider;}
signals:
			void dataArrived(PayloadPtr payload) ;
			void stateChanged(const SessionState &state);
			void errorHappened(const ConnectionErrorInfo &error);

			protected slots:
				void onDataArrived(PayloadPtr payload);

				void onStateChanged(const SessionState &state);
				void onErrorHappened(const ConnectionErrorInfo &error);

				void onLoginTimeout();
		private:
			void login();
			void processLogin(PayloadPtr loginResponse);
			void processConnected();
			void processDisconnected();
		protected:
			virtual void run();
			virtual void customEvent(QEvent *);

		private:
			QSharedPointer<ConnectionConfig> config;
			QSharedPointer<Connection>  connection;
			QSharedPointer<WireFormat> format;
			LoginInfoProvider provider;

			QAtomicInt messageId;
			QString sessionId;
			SessionState state;
		};
	}}
#endif // SESSION_H
